//
//  Person.m
//  RuntimeDemo
//
//  Created by zxs on 2021/2/22.
//

#import "Person.h"
#import <objc/runtime.h>

@interface Person ()

// 昵称；私有属性
@property (nonatomic, copy) NSString *nickname;

@end

@implementation Person

#pragma mark - public
// 写代码
- (void)coding {
    NSLog(@"小明在写代码");
}

// 吃饭
- (void)eating {
    NSLog(@"小明在吃饭");
}

#pragma mark - 重写描述方法
// NSLog会执行这个方法
- (NSString *)description {
    return [NSString stringWithFormat:@"<%@: %p> %@", [self class], self, [self propertyString]];
}

// po会执行这个方法
- (NSString *)debugDescription {
    return [NSString stringWithFormat:@"<%@: %p> %@", [self class], self, [self propertyString]];
}

#pragma mark - private
// 将本身的属性列表转化为一个字典
// 注意NSDictionary的Description无法显示中文
- (NSDictionary *)propertyDictionary {
    NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
    unsigned int count = 0;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    // 遍历数组，并利用kvc得到每个属性的值
    for (int i = 0; i < count; i++) {
        objc_property_t property = properties[i];
        // C函数得到的是C类型字符串，char类型数组或者指针
        const char *propertyName = property_getName(property);
        NSString *name = [NSString stringWithUTF8String:propertyName];
        // 利用KVC得到值，默认为值为nil字符串
        id value = [self valueForKey:name] ?: @"nil";
        // 添加到字典中
        [dictionary setObject:value forKey:name];
    }
    
    // 释放
    free(properties);
    
    return [dictionary copy];
}

// 将本身的属性列表拼接为一个字符串
// 自己拼接NSString，可以解决Unicode问题，比如显示中文
- (NSString *)propertyString {
    NSMutableString *resultString = [NSMutableString string];
    [resultString appendString:@"{\n"];
    unsigned int count = 0;
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    // 遍历数组，并利用kvc得到每个属性的值
    for (int i = 0; i < count; i++) {
        objc_property_t property = properties[i];
        // C函数得到的是C类型字符串，char类型数组或者指针
        const char *propertyName = property_getName(property);
        NSString *name = [NSString stringWithUTF8String:propertyName];
        // 利用KVC得到值，默认为值为nil字符串
        id value = [self valueForKey:name] ?: @"nil";
        // 添加到结果字符串中
        [resultString appendFormat:@"  %@ = %@;\n", name, value];
    }
    [resultString appendString:@"}"];
    
    // 释放
    free(properties);
    
    return [resultString copy];
}

@end
